
/*
 *	Adaption of Mark Podlipec's xanim software to Movie.app 
 *	(c) 1995 Andreas Windemuth
 */

#define VERBOSE 0

/*
 * xanim.c
 *
 * Copyright (C) 1990,1991,1992,1993,1994 by Mark Podlipec. 
 * All rights reserved.
 *
 * This software may be freely copied, modified and redistributed without
 * fee for non-commerical purposes provided that this copyright notice is
 * preserved intact on all copies and modified copies.
 * 
 * There is no warranty or other guarantee of fitness of this software.
 * It is provided solely "as is". The author(s) disclaim(s) all
 * responsibility and liability with respect to this software's usage
 * or its effect upon hardware or computer systems.
 *
 */
#define DA_REV 2.68
#define DA_MINOR_REV 5

#define SCALING 0

#include <libc.h>

#import "Animation.h"

@implementation Animation

- initFrom:(const char *)filename
{
    BOOL result;

    xa_init();
    xa_verbose = FALSE;
    xa_debug = 0;
    xa_file_flag = TRUE;
    first_file = 0;
    cur_file = Get_Anim_Hdr(cur_file, filename);
    cur_file->anim_type = Determine_Anim_Type(filename);
    cur_file->anim_flags = 0;
    switch(cur_file->anim_type)
    {
        case IFF_ANIM:
	  if (xa_verbose) fprintf(stderr,"Reading IFF File %s\n",filename);
	  result = IFF_Read_File(filename,cur_file);
	  break;
        case GIF_ANIM:
	  if (xa_verbose) fprintf(stderr,"Reading GIF File %s\n",filename);
	  result = GIF_Read_Anim(filename,cur_file);
	  break;
        case TXT_ANIM:
	  if (xa_verbose) fprintf(stderr,"Reading TXT File %s\n",filename);
	  result = TXT_Read_File(filename,cur_file);
	  break;
        case FLI_ANIM:
	  if (xa_verbose) fprintf(stderr,"Reading FLI File %s\n",filename);
	  result = Fli_Read_File(filename,cur_file);
	  break;
        case DL_ANIM:
	  if (xa_verbose) fprintf(stderr,"Reading DL File %s\n",filename);
	  result = DL_Read_File(filename,cur_file);
	  break;
        case PFX_ANIM:
	  if (xa_verbose) fprintf(stderr,"Reading PFX File %s\n",filename);
	  result = PFX_Read_File(filename,cur_file);
	  break;
#if SETFILE
        case SET_ANIM:
	  if (xa_verbose) fprintf(stderr,"Reading SET File %s\n",filename);
	  result = SET_Read_File(filename,cur_file);
	  break;
#endif
        case RLE_ANIM:
	  if (xa_verbose) fprintf(stderr,"Reading RLE File %s\n",filename);
	  result = RLE_Read_File(filename,cur_file);
	  break;
        case AVI_ANIM:
	  if (xa_verbose) fprintf(stderr,"Reading AVI File %s\n",filename);
	  result = AVI_Read_File(filename,cur_file);
	  break;
        case QT_ANIM:
	  if (xa_verbose) fprintf(stderr,"Reading QT File %s\n",filename);
	  result = QT_Read_File(filename,cur_file);
	  break;
        case NOFILE_ANIM:
	  fprintf(stderr,"File %s not found\n",filename);
	  result = FALSE;
	  break;
        default:
	  fprintf(stderr,"Unknown or unsupported animation type: %s\n",
								filename);
	  result = FALSE;
	  break;
      }
            if (result == FALSE) cur_file = Return_Anim_Hdr(cur_file);
      else
      {
#if SCALING
    ULONG tmpx,tmpy;
#endif
        /* Setup up anim header.  */
        cur_file->loop_num = DEFAULT_LOOPEACH_FLAG;

	cur_file->pause_lst = 0;

	xa_imagex = cur_file->imagex;
	xa_imagey = cur_file->imagey;
	if (xa_imagex > xa_max_imagex) xa_max_imagex = xa_imagex;
	if (xa_imagey > xa_max_imagey) xa_max_imagey = xa_imagey;

#if SCALING
	/* Handle Buffer Scaling Here */
	if ( (xa_buff_x != 0) && (xa_buff_y != 0) )
		{tmpx = xa_buff_x; tmpy = xa_buff_y;}
	else if (xa_buff_x != 0) /* if just x, then adjust y */
		{tmpx = xa_buff_x; tmpy = (xa_imagey * xa_buff_x) / xa_imagex;}
	else if (xa_buff_y != 0) /* if just y, then adjust x */
		{tmpy = xa_buff_y; tmpx = (xa_imagex * xa_buff_y) / xa_imagey;}
	else
	{
		/* handle any scaling */
	  tmpx = (ULONG)((float)(xa_imagex) * xa_bscalex);
	  if (tmpx == 0) tmpx = xa_imagex;
	  tmpy = (ULONG)((float)(xa_imagey) * xa_bscaley);
	  if (tmpy == 0) tmpy = xa_imagey;
	}
	cur_file->buffx = tmpx;
	cur_file->buffy = tmpy;

		/* Handle Display Scaling Here */
	if ( (xa_disp_x != 0) && (xa_disp_y != 0) ) 
		{tmpx = xa_disp_x; tmpy = xa_disp_y;}
	else if (xa_disp_x != 0) /* if just x, then adjust y */
		{tmpx = xa_disp_x; tmpy = (xa_imagey * xa_disp_x) / xa_imagex;}
	else if (xa_disp_y != 0) /* if just y, then adjust x */
		{tmpy = xa_disp_y; tmpx = (xa_imagex * xa_disp_y) / xa_imagey;}
	else
	{
		/* handle any scaling */
	  tmpx = (ULONG)((float)(xa_imagex) * xa_scalex);
	  if (tmpx == 0) tmpx = xa_imagex;
	  tmpy = (ULONG)((float)(xa_imagey) * xa_scaley);
	  if (tmpy == 0) tmpy = xa_imagey;
	}
	/* handle any IFF laced images */
	if ( (xa_allow_lace==TRUE) && (cur_file->anim_flags & ANIM_LACE))
		tmpy >>= 1;
	else	cur_file->anim_flags &= ~ANIM_LACE;
	cur_file->dispx = tmpx;
	cur_file->dispy = tmpy;
	if (tmpx > xa_max_disp_x) xa_max_disp_x = tmpx;
	if (tmpy > xa_max_disp_y) xa_max_disp_y = tmpy;

	if ((cmap_dither_type == CMAP_DITHER_FLOYD) && (xa_buffer_flag==FALSE))
			cur_file->anim_flags |= ANIM_3RD_BUF;
	xa_merged_anim_flags |= cur_file->anim_flags;

	/* NOTE: removed fade, remember to readd eventually */

	if (xa_time_flag == TRUE)
	{
	  LONG time_int;
	  xa_time_end = XA_Time_Read();
	  time_int = xa_time_end - xa_time_start;
	  fprintf(stderr,"time = %ld\n",time_int);
	  xa_time_start = XA_Time_Read();
	}
#endif
      } /* valid animation file */

    if (first_file == 0) return nil;

    if (first_file->anim_flags&ANIM_USE_FILE) xa_anim_flags |= ANIM_USE_FILE;
    if (xa_anim_flags & ANIM_USE_FILE)
    {
      if (xa_fd>=0) { close(xa_fd); xa_fd = -1; }
      if (xa_codec_buf) { FREE(xa_codec_buf,0x99); xa_codec_buf=0;}
      if ( (xa_fd=open(cur_file->fname,O_RDONLY,NULL)) == 0)
      { 
        fprintf(stderr,"can't open file %s for reading\n",cur_file->fname); 
        TheEnd();
      }
      xa_codec_buf = (char *)malloc( cur_file->max_fsize );
      if (xa_codec_buf==0) TheEnd1("malloc codec_buf err");
      if (VERBOSE) debug("File %s opened on %d, %d bytes allocated\n",
	    cur_file->fname, xa_fd, cur_file->max_fsize);
    }

    cur_file = first_file;
    bitmap = [[NXBitmapImageRep alloc] initData:NULL
	pixelsWide:xa_max_imagex
	pixelsHigh:xa_max_imagey
	bitsPerSample:8
	samplesPerPixel:3	// (cSpace == RGB_COLOR) ? 3 : 1
	hasAlpha:NO
	isPlanar:NO
	colorSpace:NX_RGBColorSpace
	bytesPerRow:0
	bitsPerPixel:32
    ];
    if (!bitmap) {
	warning("Could not create bitmap\n");
	return nil;
    }
    if (VERBOSE) debug("Created Image %d %d %d\n", xa_max_imagex, xa_max_imagey, 24);
    return self;
}

- free;
{
    [bitmap free];
    return self;
}

- (NXBitmapImageRep *)update
{
    XA_ACTION *act;
    ACT_DLTA_HDR *d;
    ULONG xs, ys, xe, ye;
    
    if ( (act = cur_file->frame_lst[cur_frame].act) != 0) {
	if (VERBOSE) debug("Action %d, type %ld chdr %x map %x\n", cur_frame, 
	    act->type, act->chdr, act->chdr->map);
	if (act->type!=ACT_DELTA) {
	    warning("Action type %d not supported\n", act->type);
	    return nil;
	}
    } else {
	warning("No Action in frame\n");
	return nil;
    }
    d = (ACT_DLTA_HDR *)act->data;
    if (!d) {
	warning("No Delta in action\n");
	return nil;
    }
    if (VERBOSE) debug(
	"Delta %ld %ld %ld %ld flags=%lx special=%lx extra=%lx fpos=%ld fsize=%ld\n",
	d->xpos, d->ypos, d->xsize, d->ysize, d->flags, d->special, d->extra, d->fpos, d->fsize
    );
    if ((xa_fd >= 0) && (!(d->flags & DLTA_DATA)) ) {
	XA_Read_Delta(xa_codec_buf, xa_fd, d->fpos, d->fsize);
	if (VERBOSE) debug("% bytes read at %d from %d\n", d->fsize, d->fpos, xa_fd);
	d->delta([bitmap data], xa_codec_buf, d->fsize, act->chdr, act->chdr->map, 1,
	    d->xsize,d->ysize,24, &xs,&ys,&xe,&ye,d->special,d->extra);
	d->delta([bitmap data], xa_codec_buf, d->fsize,
	    act->chdr, act->chdr->map, 1, d->xsize,d->ysize,24,
	    &xs,&ys,&xe,&ye,d->special,d->extra);
    } else {
	d->delta([bitmap data], d->data, d->fsize, act->chdr, act->chdr->map, 1,
	    d->xsize,d->ysize,24, &xs,&ys,&xe,&ye,d->special,d->extra);
    }
    if (VERBOSE) debug("Delta area: %ld %ld %ld %ld\n", xs, ys, xe, ye);
    return bitmap;
}

- getMaxSize:(NXSize *)size
{
    size->width = xa_max_imagex;
    size->height = xa_max_imagey;
    return self;
}

- (NXBitmapImageRep *)next
{
    Step_Frame_Next();
    return [self update];
}

- (BOOL)isLast
{
    return (cur_frame==cur_file->last_frame);
}

- (NXBitmapImageRep *)bitmap;
{
    return bitmap;
}

@end
